package com.jbpm.action;

import com.jbpm.vo.BaoxiaoVO;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.GraphSession;
import org.jbpm.file.def.FileDefinition;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.jbpm.taskmgmt.exe.TaskMgmtInstance;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class LoginAction extends ActionSupport{

	private String actorId;//获取登录名称
	private String nextPath;
	private String meetingmember;//参会人员
	private long tiid;
	private BaoxiaoVO baoxiao;
	private List myTaskList;
	private List taskNext;
	private File pdFile;//上传流程文件
	private String pdname;//上传流程的名称
	public String getPdname() {
		return pdname;
	}

	public void setPdname(String pdname) {
		this.pdname = pdname;
	}

	public File getPdFile() {
		return pdFile;
	}

	public void setPdFile(File pdFile) {
		this.pdFile = pdFile;
	}

	public List getTaskNext() {
		return taskNext;
	}

	public void setTaskNext(List taskNext) {
		this.taskNext = taskNext;
	}

	public BaoxiaoVO getBaoxiao() {
		return baoxiao;
	}

	public void setBaoxiao(BaoxiaoVO baoxiao) {
		this.baoxiao = baoxiao;
	}

	public String getActorId() {
		return actorId;
	}

	public void setActorId(String actorId) {
		this.actorId = actorId;
	}

	public String login() throws Exception{

		//设置session
		ActionContext.getContext().getSession().put("actorId", actorId);

		return SUCCESS;
	}
	//查看最新流程
	public String list() throws Exception{
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		//查询所有流程的最新版本
		myTaskList = ctx.getGraphSession().findLatestProcessDefinitions();
	  	ctx.close();

		return "list";
	}
	//查看指定流程的所有版本
	public String allversion() throws Exception{
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		myTaskList = ctx.getGraphSession().findAllProcessDefinitionVersions(pdname);
	 	ctx.close();
		return "allversion";
	}
	//发布流程
	public String deploy() throws Exception{
		//创建JBPM上下文环境
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		//获取流程文件路径
		String path = "";
		path = ServletActionContext.getRequest().getRealPath("/");
		path += "WEB-INF/classes/processdefinition.xml";
		System.out.println(path);
		File file = new File(path);
		FileInputStream fis = new FileInputStream(file);
		//定义流程类
		ProcessDefinition pd = ProcessDefinition.parseXmlInputStream(fis);
		//发布流程
		ctx.deployProcessDefinition(pd);
		ctx.close();
		System.out.println("finished.......");
		return "list";
	}

	/**
	 * 给节点的actor-id动态赋值：
	 * 1.定义变量
	 *  定义actorId变量，给填报销单，领取费用节点的变量赋值
	 *	pi.getContextInstance().createVariable("actorId", baoxiao.getUsername());
	 *	<task name="填报销单" actor-id="#{actorId}"></task>
	 * 2.定义泳道，给泳道设值
	 * <swimlane name="startor">
	 *	<assignment actor-id="#{actorId}"></assignment>
	 *	</swimlane>
	 *	<task name="填报销单" swimlane="startor"></task>
	 * 3.如果泳道名称为initiator，可以不设置变量,但是要设置
	 *  <task name="填报销单" swimlane="initiator"></task>
	 *  ctx.setActorId（actorId）的值
	 * 4.通过类动态决定actor-id的值
	 * 	1.定义一个类实现AssignmentHandler接口，重写assign
	 * <task name="部门经理审批">
	 *		<assignment class="ht.service.AssignedMgr"></assignment>
	 *	</task>
	 *
	 *
	 *--发布流程表
		select * from dbo.JBPM_PROCESSDEFINITION
		--流程任务表
		select * from dbo.JBPM_TASK
		select * from baoxiao
		select * from dbo.JBPM_PROCESSINSTANCE
		select * from dbo.JBPM_TASKINSTANCE
		select * from dbo.JBPM_VARIABLEINSTANCE
	 * */
	//启动流程
	public String add() throws Exception{
		//创建JBPMContext对象
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		//保存报销表的数据
		//ctx.getSession就是获取hibernate的session对象
		ctx.getSession().save(baoxiao);
		//找到要启动的最新版本的流程
	//	ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition("qingjia");
//		ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition("baoxiao");
		//签到
//		ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition("meeting");
		//会签
//		ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition("Meetings");
		//呼叫中心callCenter
		ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition("Tel");
//		ProcessDefinition pd = ctx.getGraphSession().findLatestProcessDefinition(pdname);

		//创建流程实例
		ProcessInstance pi = new ProcessInstance(pd);
		//创建变量，使流程与报销单建立联系
		pi.getContextInstance().createVariable("infoid", baoxiao.getOid());
		//定义actorId变量，给填报销单，领取费用节点的变量赋值,actorId变量名称是固定的，不能变
		pi.getContextInstance().createVariable("actorId", baoxiao.getUsername());
		//定义money变量，在流程的decision节点中使用
		pi.getContextInstance().createVariable("money", baoxiao.getMoney());
		//meetingmember
		pi.getContextInstance().createVariable("meetingmember",meetingmember);
//		如果泳道名称为initiator，则必须通过该函数设置actorId的值
		ctx.setActorId(baoxiao.getUsername());
		//启动流程
		TaskMgmtInstance taskMgmtInstance = pi.getTaskMgmtInstance();
		TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();
		ti.start();//开始填单
		ti.end();//填单结束
		//完成当前步骤后，会马上生成下一步的数据
		ctx.close();


		return "mytask";
	}
	//取出任务列表
	public String mytask() throws Exception{

		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		actorId =ActionContext.getContext().getSession().get("actorId").toString();
		myTaskList= ctx.getTaskMgmtSession().findTaskInstances(actorId);
		//抢任务
		List list= ctx.getTaskMgmtSession().findPooledTaskInstances(actorId);
		if(list !=null){
			myTaskList.addAll(list);
		}
		ctx.close();
		return "mytask";
	}
//	//抢任务时用该函数，取出任务列表
//	public String pooltask() throws Exception{
//
//		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
//		actorId =ActionContext.getContext().getSession().get("actorId").toString();
//		myTaskList= ctx.getTaskMgmtSession().findPooledTaskInstances(actorId);
//		return "mytask";
//	}
	//获取下一步的数据
	public String getNext() throws Exception{
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		//获取当前的任务节点
		TaskInstance ti = ctx.getTaskInstance(tiid);
		//获取报销单
		long infoid = (Long)ti.getContextInstance().getVariable("infoid");
		baoxiao = (BaoxiaoVO)ctx.getSession().get(BaoxiaoVO.class, infoid);
		//获取下一步操作列表
		taskNext = ti.getTask().getTaskNode().getLeavingTransitions();
		System.out.println("next size="+taskNext.size());
		actorId = ActionContext.getContext().getSession().get("actorId").toString();
		ti.setActorId(actorId);//当执行抢任务时，有该函数传值给actorId
		//ti.start(actorId);
		//让任务开始
		if(ti.getStart() == null)
			ti.start();
		ctx.close();
		return "getNext";
	}
	//结束当前任务
	public String saveNext() throws Exception{
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		TaskInstance ti = ctx.loadTaskInstance(tiid);
		if(nextPath==null || nextPath.equals(""))
			ti.end();//结束当前任务，进入下一个任务
		else
		{
			ti.end(nextPath);//流程进入指定的节点
		}
		ctx.close();
		return mytask();
	}
	public String exit() throws Exception{
		ServletActionContext.getRequest().getSession().invalidate();
		return INPUT;
	}

	public List getMyTaskList() {
		return myTaskList;
	}

	public void setMyTaskList(List myTaskList) {
		this.myTaskList = myTaskList;
	}

	public long getTiid() {
		return tiid;
	}

	public void setTiid(long tiid) {
		this.tiid = tiid;
	}

	public String getNextPath() {
		return nextPath;
	}

	public void setNextPath(String nextPath) {
		this.nextPath = nextPath;
	}

	public String getMeetingmember() {
		return meetingmember;
	}

	public void setMeetingmember(String meetingmember) {
		this.meetingmember = meetingmember;
	}
	/**
	 * 上传流程定义文件
	 * @return
	 */
	public String upload() throws Exception{
		//JBPMContext会检查数据表是否已存在，如果没有就去创建表
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		//流程定义文件相关的操作，数据库操作的session
		GraphSession ghsesion =  ctx.getGraphSession();
		//上传流程定义文件
		//1、获取流程定义文件
		ProcessDefinition pd;
		try {
			System.out.println(pdFile);
			System.out.println(pdFile.getName()+" : "+pdFile.getAbsolutePath());
			//仅仅上传processdefinition.xml文件
			//pd = ProcessDefinition.parseXmlInputStream(new FileInputStream(pdFile));
			//上传ZIP文件，包含gpd.xml,processdefinition.xml,processimage.jpg
			pd = ProcessDefinition.parseParZipInputStream(new ZipInputStream(new FileInputStream(pdFile)));
			//2、部署流程定义文件 将流程定义文件保存到数据库
			ghsesion.deployProcessDefinition(pd);
			pdname = pd.getName();
		} catch (Exception e) {
			e.printStackTrace();
		}
		//3、关闭上下文对象
		ctx.close();
		System.out.println("upload...");
		return list();
	}
	/**
	 *查看流程图
	 * @return
	 */
	public String toView(){
		try {
			HttpServletResponse resp =  ServletActionContext.getResponse();

			//JBPMContext
			JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();

			//流程定义文件相关的操作
			GraphSession ghsesion =  ctx.getGraphSession();
//		Map map =  ghsesion.getProcessDefinition(id).getDefinitions();
			FileDefinition file =  ghsesion.getProcessDefinition(tiid).getFileDefinition();
			System.out.println("file = "+file);
			Map maps =  file.getBytesMap();
			Iterator iter =  maps.keySet().iterator();

			resp.setContentType("image/jpg");//在页面只显示图片
			OutputStream out = resp.getOutputStream();
			while(iter.hasNext()){
				String key = iter.next().toString();
				if(key.indexOf(".jpg")!=-1){
					byte [] bs= (byte[])maps.get(key);
					out.write(bs,0,bs.length);
					out.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 导出流程定义文件ZIP
	 * @return
	 */
	public String toExport(){
		try {
			HttpServletResponse resp =  ServletActionContext.getResponse();

			//JBPMContext
			JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();

			//流程定义文件相关的操作
			GraphSession ghsesion =  ctx.getGraphSession();
			ProcessDefinition pd = ghsesion.getProcessDefinition(tiid);
			FileDefinition file =  pd.getFileDefinition();
			Map maps =  file.getBytesMap();//会生成与上传时一样的文件（3个文件）
			Iterator iter =  maps.keySet().iterator();

			//设置response对象的头参数，attachment就是附件，filename=文件名称
			resp.setHeader("Content-disposition","attachment;filename=" +pd.getName()+"_"+pd.getVersion()+".zip" );
			//下载的文件类型是zip文件
			resp.setContentType("application/x-zip-compressed");
			OutputStream out = resp.getOutputStream();
			ZipOutputStream zipo = new ZipOutputStream(out);
			while(iter.hasNext()){
				String key = iter.next().toString();
				byte [] bs= (byte[])maps.get(key);//某个文件的内容
				ZipEntry ze = new ZipEntry(key);
				zipo.putNextEntry(ze);
				zipo.write(bs,0,bs.length);
				zipo.closeEntry();
			}
			zipo.flush();
			zipo.close();
			out.flush();
			out.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;

	}
	/**
	 * 根据流程ID删除流程定义文件
	 * @return
	 */
	public String delete() throws Exception{
		JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
		GraphSession gsession =  ctx.getGraphSession();
		System.out.println(tiid);
		gsession.deleteProcessDefinition(tiid);
		ctx.close();
		return allversion();
	}
}
